package controllers;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import repository.FriendRequestRepository;
import repository.ProfileRepository;
import repository.SearchRepository;
import repository.UserRepository;
import util.EmailSender;
import util.MailTitleBody;
import util.MailTitleBody.MailTitleBodyEnum;
import validator.BasicInfoFormValidator;
import validator.ContactInfoFormValidator;
import validator.ForgotPasswordValidator;
import validator.GraduateFormValidator;
import validator.ProfessionalInfoFormValidator;
import validator.ProfilePictureFormValidator;
import validator.UpdatePasswordFormValidator;
import validator.UpdateUserFormValidator;
import validator.UserFormValidator;

import com.google.code.linkedinapi.client.LinkedInApiClient;
import com.google.code.linkedinapi.client.LinkedInApiClientException;
import com.google.code.linkedinapi.client.LinkedInApiClientFactory;
import com.google.code.linkedinapi.client.oauth.LinkedInAccessToken;
import com.restfb.DefaultFacebookClient;
import com.restfb.FacebookClient;
import com.restfb.exception.FacebookOAuthException;
import command.BasicInfoForm;
import command.ContactInfoForm;
import command.EditResultForm;
import command.ForgotPasswordForm;
import command.GraduateForm;
import command.MassiveRequestForm;
import command.MassiveSaveForm;
import command.ProfessionalInfoForm;
import command.ProfilePictureForm;
import command.UpdatePasswordForm;
import command.UpdateUserForm;
import command.UserForm;

import domain.FacebookUser;
import domain.FriendRequest;
import domain.Profile;
import domain.SearchResultItem;
import domain.SocialToken;
import domain.User;
import domain.exceptions.DuplicateException;
import domain.exceptions.DuplicateException.DupErrorCode;

@Controller
@RequestMapping("admin")
public class UserController {

	private UserRepository userRepository;
	private FriendRequestRepository friendRequestRepository;
	private SearchRepository searchRepository;
	private UserFormValidator validator;
	private UpdateUserFormValidator updateValidator;
	private UpdatePasswordFormValidator updatePasswordValidator;
	private GraduateFormValidator graduateFormValidator;
	private ForgotPasswordValidator forgotPasswordValidator;
	private BasicInfoFormValidator basicInfoFormValidator;
	private ProfilePictureFormValidator profilePictureFormValidator;
	private ContactInfoFormValidator contactInfoFormValidator;
	private ProfessionalInfoFormValidator professionalInfoFormValidator;
	private MessageSource msgSrc; 
	//TODO esto no va aca. meter en bd
	private final String LINKEDIN_API_KEY = "rnaeme79uqz5";
	private final String LINKEDIN_API_SECRET = "nz5A3kPcwP0yzkfs";
	

	@Autowired
	public UserController(UserRepository userRepository,
			FriendRequestRepository friendRequestRepository,
			SearchRepository searchRepository,
			ProfileRepository profileRepository, 
			UserFormValidator validator,
			UpdateUserFormValidator updateValidator,
			UpdatePasswordFormValidator updatePasswordValidator,
			GraduateFormValidator graduateFormValidator,
			BasicInfoFormValidator basicInfoFormValidator,
			ForgotPasswordValidator forgotPasswordValidator,
			ProfilePictureFormValidator profilePictureFormValidator,
			ContactInfoFormValidator contactInfoFormValidator,
			ProfessionalInfoFormValidator professionalInfoFormValidator,
			MessageSource msgSrc) {
		this.userRepository = userRepository;
		this.friendRequestRepository = friendRequestRepository;
		this.searchRepository = searchRepository;
		this.validator = validator;
		this.updateValidator = updateValidator;
		this.updatePasswordValidator = updatePasswordValidator;
		this.graduateFormValidator = graduateFormValidator;
		this.forgotPasswordValidator = forgotPasswordValidator;
		this.basicInfoFormValidator = basicInfoFormValidator;
		this.profilePictureFormValidator = profilePictureFormValidator;
		this.contactInfoFormValidator = contactInfoFormValidator;
		this.professionalInfoFormValidator = professionalInfoFormValidator;
		this.msgSrc = msgSrc;
	}

	@RequestMapping(method = RequestMethod.GET)
	public ModelAndView RequestUserCreation() {
		ModelAndView mav = new ModelAndView();
		mav.addObject("graduateForm", new GraduateForm());
		mav.addObject("title", "Solicitar Alta de Cuenta");
		mav.setViewName("user/RequestUserCreation");
		return mav;
	}

	@RequestMapping(method = RequestMethod.POST)
	public ModelAndView RequestUserCreation(HttpSession session,
			GraduateForm graduateForm, Errors errors) {
		ModelAndView mav = new ModelAndView();
		graduateFormValidator.validate(graduateForm, errors);
		if (errors.hasErrors()) {
			return mav;
		}
		try {
			User user = new User(graduateForm.getDocNumber(),
					graduateForm.getPassword(), graduateForm.getName(),
					graduateForm.getLastName(), graduateForm.getEmail(), false,
					false);
			Profile profile = new Profile(user, graduateForm.getStudentCode(), graduateForm.getBirthdate(), null, null);
			user.setProfile(profile);
			userRepository.newUser(user);
			mav.addObject("messages", msgSrc.getMessage("solicitudCuentaEnviada", null,null));
		} catch (DuplicateException e) {
			errors.rejectValue("docNumber", e.getErrorCode().toString());
		}
		if (errors.hasErrors()) {
			mav.addObject("title", msgSrc.getMessage("altaCuentaTitle", null,null));
			return mav;
		}
		//mav.setViewName("redirect:/bin/general/index");
		mav.setViewName("general/index");
		return mav;
	}

	@RequestMapping(method = RequestMethod.GET)
	public ModelAndView AbmUsers() {
		ModelAndView mav = new ModelAndView();
		mav.addObject("userForm", new UserForm());
		mav.addObject("title", msgSrc.getMessage("crearAdminTitle", null,null));
		mav.addObject("action", "../user/AbmUsers");
		mav.setViewName("user/AbmUsers");
		return mav;
	}

	@RequestMapping(method = RequestMethod.POST)
	public ModelAndView AbmUsers(HttpSession session, UserForm userForm,
			Errors errors) {
		ModelAndView mav = new ModelAndView();
		validator.validate(userForm, errors);
		if (errors.hasErrors()) {
			return mav;
		}
		try {
			User usuario = new User(userForm.getDocNumber(),
					userForm.getPassword(), userForm.getName(),
					userForm.getLastName(), userForm.getEmail(), true, true);
			userRepository.newUser(usuario);
		} catch (DuplicateException e) {
			if (e.getErrorCode()==DupErrorCode.DUP_DOC_NUMBER){
				errors.rejectValue("docNumber", "dupDocNumber");
			}else if (e.getErrorCode()==DupErrorCode.DUP_EMAIL){
				errors.rejectValue("email", "dupEmail");
			}
		}
		if (errors.hasErrors()) {
			mav.addObject("title", msgSrc.getMessage("crearAdminTitle", null,null));
			mav.addObject("action", "../user/AbmUsers");
			return mav;
		}
		mav.setViewName("redirect:/bin/general/index");
		return mav;
	}

	@RequestMapping(method = RequestMethod.GET)
	public ModelAndView UpdatePassword(HttpSession session) {
		ModelAndView mav = new ModelAndView();
													
		UpdatePasswordForm updatePasswordForm = new UpdatePasswordForm();

		mav.addObject("updatePasswordForm", updatePasswordForm);
		mav.addObject("title", msgSrc.getMessage("cambiarPasswordTitle", null,null));
		mav.addObject("action", "../user/UpdatePassword");
		mav.setViewName("user/UpdatePassword");
		return mav;
	}

	@RequestMapping(method = RequestMethod.POST)
	public ModelAndView UpdatePassword(HttpSession session, UpdatePasswordForm updatePasswordForm, Errors errors) {
		ModelAndView mav = new ModelAndView();
		updatePasswordValidator.validate(updatePasswordForm, errors);
		if (errors.hasErrors()) {
			mav.addObject("updatePasswordForm", updatePasswordForm);
			mav.addObject("title", msgSrc.getMessage("cambiarPasswordTitle", null,null));
			mav.addObject("action", "../user/UpdatePassword");
			mav.setViewName("user/UpdatePassword");
			return mav;
		}

		User userlogged = (User) session.getAttribute("user");
		User userMod = userRepository.getUserByDocNumber(userlogged.getDocNumber());
		updatePasswordForm.update(userMod);

		mav.setViewName("user/EditProfile");
		mav.addObject("tab", "editBasicInfo");
		mav.addObject("BasicInfoForm", new BasicInfoForm(userMod));
		mav.addObject("ProfilePictureForm", new ProfilePictureForm(userMod));
		mav.addObject("ContactInfoForm", new ContactInfoForm(userMod));
		mav.addObject("ProfessionalInfoForm", new ProfessionalInfoForm(userMod));
		mav.addObject("user", userMod);
		session.setAttribute("user", userMod);
		mav.addObject("messages", msgSrc.getMessage("perfilEditadoOk", null,null));
		return mav;
	}

	@RequestMapping(method = RequestMethod.GET)
	public ModelAndView ModifyUser(HttpSession session, @RequestParam("userid") User user) {
		ModelAndView mav = new ModelAndView();
		UpdateUserForm updateUserForm = new UpdateUserForm(user);

		mav.addObject("updateUserForm", updateUserForm);
		mav.addObject("title", msgSrc.getMessage("editarAdminTitle", null,null));
		mav.addObject("action", "../user/ModifyUser");
		mav.setViewName("user/UpdateUsers");
		return mav;
	}

	@RequestMapping(method = RequestMethod.POST)
	public ModelAndView ModifyUser(HttpSession session,
			UpdateUserForm editUserForm, Errors errors) {
		ModelAndView mav = new ModelAndView();
		updateValidator.validate(editUserForm, errors);
		// if there is someone in the DB with the same email, and do not have
		// the same doc number -> ERROR
		User usrWthSameEmail = userRepository.getUserByEmail(editUserForm.getEmail());
		if (usrWthSameEmail != null && !usrWthSameEmail.getDocNumber().equals(editUserForm.getDocNumber())) {
			errors.rejectValue("email", "dupEmailAdmin");
		}
		if (errors.hasErrors()) {
			mav.addObject("editUserForm", editUserForm);
			mav.addObject("title", msgSrc.getMessage("editarAdminTitle", null,null));
			mav.addObject("action", "../user/ModifyUser");
			mav.addObject("username", editUserForm.getDocNumber());
			mav.setViewName("user/UpdateUsers");
			return mav;
		}

		User userMod = userRepository.getUserByDocNumber(editUserForm.getDocNumber());
		editUserForm.update(userMod);

		User userlogged = (User) session.getAttribute("user");
		if (userlogged.getDocNumber().equals(userMod.getDocNumber())) {
			session.setAttribute("user", userMod);
		}
		return ListAdmins(session);
	}

	@RequestMapping(method = RequestMethod.GET)
	public ModelAndView DeactivateAccount(HttpSession session) {
		ModelAndView mav = new ModelAndView();
		User userlogged = (User) session.getAttribute("user");
		if (userlogged.isAdmin()) {
			mav.addObject("errorTitle", "Error");
			mav.addObject("errorMsg", msgSrc.getMessage("errorBorrarPropioUsuario", null,null));
			mav.setViewName("general/error");
			return mav;
		}
		userRepository.getUserByDocNumber(userlogged.getDocNumber()).setActive(false);
		userlogged.setActive(false);
		session.setAttribute("title",msgSrc.getMessage("cuentaDesactivada", null,null));
		mav.setViewName("redirect:/bin/general/logout");
		return mav;
	}

	@RequestMapping(method = RequestMethod.GET)
	public ModelAndView DeleteUser(HttpSession session, @RequestParam("userid") User user) {
		ModelAndView mav = new ModelAndView();
		User userlogged = (User) session.getAttribute("user");
		if (userlogged.equals(user)) {
			mav.addObject("errorTitle", "Error");
			mav.addObject("errorMsg", msgSrc.getMessage("errorBorrarPropioUsuario2", null,null));
			mav.setViewName("general/error");
			return mav;
		}
		if (!user.isAdmin()) {
			mav.addObject("errorTitle", "Error");
			mav.addObject("errorMsg", msgSrc.getMessage("errorBorrarEgresado", null,null));
			mav.setViewName("general/error");
			return mav;
		}
		userRepository.deleteUser(user);
		return ListAdmins(session);
	}

	@RequestMapping(method = RequestMethod.GET)
	public ModelAndView viewResult(HttpSession session, @RequestParam("resultId") SearchResultItem result, 
			@RequestParam("searchResultId") int searchResultId) {
		ModelAndView mav = viewProfile(session, result.getUser());
		mav.addObject("result", result);
		mav.addObject("searchResultId", searchResultId);
		mav.addObject("editResultForm", new EditResultForm(result));
		mav.setViewName("user/viewResult");
		return mav;
	}
	
	@RequestMapping(method = RequestMethod.GET)
	public ModelAndView viewProfile(HttpSession session, @RequestParam("userid") User user) {
		ModelAndView mav = new ModelAndView();
		mav.addObject("userProfile", user);
		SocialToken stoken = user.getSocialToken();
		boolean gotPermissionsForLinkedin = false;
		boolean gotPermissionsForFacebook = false;
		
		if (stoken != null) {
			if (stoken.getLinkedInToken() != null && stoken.getLinkedinTokenSecret() != null) {
				LinkedInAccessToken accessToken = new LinkedInAccessToken(
						stoken.getLinkedInToken(), stoken.getLinkedinTokenSecret());
				LinkedInApiClientFactory factory = LinkedInApiClientFactory.newInstance(
						LINKEDIN_API_KEY, LINKEDIN_API_SECRET);
				LinkedInApiClient client = factory.createLinkedInApiClient(accessToken);
				try {
					client.getProfileForCurrentUser();
					// if we are here, tokens still work, so no need to ask user
					// for permission.
					gotPermissionsForLinkedin = true;
				} catch (LinkedInApiClientException e) {
					// if we got here, it means old tokens dont work anymore, so
					// we ask them again
				}
			}
			if (stoken.getFacebooktoken() != null) {
				FacebookClient facebookClient = new DefaultFacebookClient(stoken.getFacebooktoken());
				try {
					facebookClient.fetchObject("me", FacebookUser.class);
					gotPermissionsForFacebook = true;
				} catch (FacebookOAuthException e) {
					// if we got here, it means old tokens dont work anymore
				} catch (com.restfb.json.JsonException e) {
					// should not happen
				}
				
				 
			}
		}
	
		User userlogged = (User) session.getAttribute("user");
		// Traigo el user de nuevo desde la base porque el que esta en la session no mantiene actualizado los cambios de amistades
		User userloggedrefreshed = userRepository.getUser(userlogged.getId());
		boolean isLoggedProfile = userlogged.equals(user);
		boolean isAdmin = userlogged.isAdmin();
		mav.addObject("isLoggedProfile", isLoggedProfile);
		mav.addObject("isAdmin", isAdmin);
		if (!isAdmin && !isLoggedProfile) {
			boolean isFriend = userloggedrefreshed.getFriends().contains(user);
			mav.addObject("isFriend", isFriend);
			if (!isFriend) {
				mav.addObject("hasRequestedFriendship", friendRequestRepository.getFriendRequestsByUser(userloggedrefreshed).contains(user));
			}
		}
		mav.addObject("gotPermissionsForLinkedin", gotPermissionsForLinkedin);
		mav.addObject("gotPermissionsForFacebook", gotPermissionsForFacebook);
		mav.setViewName("user/viewProfile");
		return mav;		
	}
	
	@RequestMapping(method = RequestMethod.GET)
	public ModelAndView EditProfile(HttpSession session) {
		ModelAndView mav = new ModelAndView();
		User user = (User) session.getAttribute("user");
		mav.addObject("tab", "editBasicInfo");
		mav.addObject("BasicInfoForm", new BasicInfoForm(user));
		mav.addObject("ProfilePictureForm", new ProfilePictureForm(user));
		mav.addObject("ContactInfoForm", new ContactInfoForm(user));
		mav.addObject("ProfessionalInfoForm", new ProfessionalInfoForm(user));
		mav.addObject("user", user);
		mav.setViewName("user/EditProfile");
		return mav;
	}

	@RequestMapping(method = RequestMethod.POST)
	public ModelAndView EditBasicInfo(HttpSession session, BasicInfoForm basicInfoForm, Errors errors) {
		ModelAndView mav = new ModelAndView();
		mav.setViewName("user/EditProfile");
		basicInfoFormValidator.validate(basicInfoForm, errors);
		User user = (User) session.getAttribute("user");
		mav.addObject("errors", errors.hasErrors());
		mav.addObject("tab", "editBasicInfo");
		if (errors.hasErrors()) {
			mav.addObject("user", user);
			mav.addObject("BasicInfoForm", basicInfoForm);
			mav.addObject("ProfilePictureForm", new ProfilePictureForm(user));
			mav.addObject("ContactInfoForm", new ContactInfoForm(user));
			mav.addObject("ProfessionalInfoForm", new ProfessionalInfoForm(user));
			mav.addObject("errorLogin", msgSrc.getMessage("errorEditarPerfil", null,null));
			return mav;
		}
		User userMod = userRepository.getUserByDocNumber(user.getDocNumber());
		basicInfoForm.update(userMod);
		mav.addObject("BasicInfoForm", new BasicInfoForm(userMod));
		mav.addObject("ProfilePictureForm", new ProfilePictureForm(userMod));
		mav.addObject("ContactInfoForm", new ContactInfoForm(userMod));
		mav.addObject("ProfessionalInfoForm", new ProfessionalInfoForm(userMod));
		mav.addObject("user", userMod);
		session.setAttribute("user", userMod);
		mav.addObject("messages", msgSrc.getMessage("perfilEditadoOk", null,null));
		return mav;
	}

	@RequestMapping(method = RequestMethod.POST)
	public ModelAndView EditProfilePicture(HttpSession session, ProfilePictureForm profilePictureForm, Errors errors) {
		ModelAndView mav = new ModelAndView();
		mav.setViewName("user/EditProfile");
		profilePictureFormValidator.validate(profilePictureForm, errors);
		User user = (User) session.getAttribute("user");
		mav.addObject("errors", errors.hasErrors());
		mav.addObject("tab", "editProfilePicture");
		if (errors.hasErrors()) {
			mav.addObject("user", user);
			mav.addObject("BasicInfoForm", new BasicInfoForm(user));
			mav.addObject("ProfilePictureForm", profilePictureForm);
			mav.addObject("ContactInfoForm", new ContactInfoForm(user));
			mav.addObject("ProfessionalInfoForm", new ProfessionalInfoForm(user));
			mav.addObject("errorLogin", msgSrc.getMessage("errorEditarPerfil", null,null));
			return mav;
		}
		User userMod = userRepository.getUserByDocNumber(user.getDocNumber());
		profilePictureForm.update(userMod);
		mav.addObject("BasicInfoForm", new BasicInfoForm(userMod));
		mav.addObject("ProfilePictureForm", new ProfilePictureForm(userMod));
		mav.addObject("ContactInfoForm", new ContactInfoForm(userMod));
		mav.addObject("ProfessionalInfoForm", new ProfessionalInfoForm(userMod));
		mav.addObject("user", userMod);
		session.setAttribute("user", userMod);
		mav.addObject("messages", msgSrc.getMessage("perfilEditadoOk", null,null));
		return mav;
	}

	@RequestMapping(method = RequestMethod.GET)
	public ModelAndView DeleteProfilePicture(HttpSession session) {
		ModelAndView mav = new ModelAndView();
		mav.setViewName("user/EditProfile");
		User user = (User) session.getAttribute("user");
		User userMod = userRepository.getUserByDocNumber(user.getDocNumber());
		userMod.getProfile().setPhoto(null);
		mav.addObject("tab", "editProfilePicture");
		mav.addObject("BasicInfoForm", new BasicInfoForm(userMod));
		mav.addObject("ProfilePictureForm", new ProfilePictureForm(userMod));
		mav.addObject("ContactInfoForm", new ContactInfoForm(userMod));
		mav.addObject("ProfessionalInfoForm", new ProfessionalInfoForm(userMod));
		mav.addObject("user", userMod);
		session.setAttribute("user", userMod);
		mav.addObject("messages", msgSrc.getMessage("perfilEditadoOk", null,null));
		return mav;
	}
	
	@RequestMapping(method = RequestMethod.POST)
	public ModelAndView EditContactInfo(HttpSession session, ContactInfoForm contactInfoForm, Errors errors) {
		ModelAndView mav = new ModelAndView();
		mav.setViewName("user/EditProfile");
		contactInfoFormValidator.validate(contactInfoForm, errors);
		User user = (User) session.getAttribute("user");
		mav.addObject("errors", errors.hasErrors());
		mav.addObject("tab", "editContactInfo");
		if (errors.hasErrors()) {
			mav.addObject("user", user);
			mav.addObject("BasicInfoForm", new BasicInfoForm(user));
			mav.addObject("ProfilePictureForm", new ProfilePictureForm(user));
			mav.addObject("ContactInfoForm", contactInfoForm);
			mav.addObject("ProfessionalInfoForm", new ProfessionalInfoForm(user));
			mav.addObject("errorLogin", msgSrc.getMessage("errorEditarPerfil", null,null));
			return mav;
		}
		User userMod = userRepository.getUserByDocNumber(user.getDocNumber());
		contactInfoForm.update(userMod);
		mav.addObject("BasicInfoForm", new BasicInfoForm(userMod));
		mav.addObject("ProfilePictureForm", new ProfilePictureForm(userMod));
		mav.addObject("ContactInfoForm", new ContactInfoForm(userMod));
		mav.addObject("ProfessionalInfoForm", new ProfessionalInfoForm(userMod));
		mav.addObject("user", userMod);
		session.setAttribute("user", userMod);
		mav.addObject("messages", msgSrc.getMessage("perfilEditadoOk", null,null));
		return mav;
	}
	
	@RequestMapping(method = RequestMethod.POST)
	public ModelAndView EditProfessionalInfo(HttpSession session, ProfessionalInfoForm professionalInfoForm, Errors errors) {
		ModelAndView mav = new ModelAndView();
		mav.setViewName("user/EditProfile");
		professionalInfoFormValidator.validate(professionalInfoForm, errors);
		User user = (User) session.getAttribute("user");
		mav.addObject("errors", errors.hasErrors());	
		mav.addObject("tab", "editProfessionalInfo");
		if (errors.hasErrors()) {
			mav.addObject("user", user);
			mav.addObject("BasicInfoForm", new BasicInfoForm(user));
			mav.addObject("ProfilePictureForm", new ProfilePictureForm(user));
			mav.addObject("ContactInfoForm", new ContactInfoForm(user));
			mav.addObject("ProfessionalInfoForm", professionalInfoForm);
			mav.addObject("errorLogin", msgSrc.getMessage("errorEditarPerfil", null,null));
			return mav;
		}
		User userMod = userRepository.getUserByDocNumber(user.getDocNumber());
		professionalInfoForm.update(userMod);
		mav.addObject("BasicInfoForm", new BasicInfoForm(userMod));
		mav.addObject("ProfilePictureForm", new ProfilePictureForm(userMod));
		mav.addObject("ContactInfoForm", new ContactInfoForm(userMod));
		mav.addObject("ProfessionalInfoForm", new ProfessionalInfoForm(userMod));
		mav.addObject("user", userMod);
		session.setAttribute("user", userMod);
		mav.addObject("messages", msgSrc.getMessage("perfilEditadoOk", null,null));
		return mav;
	}
	

	@RequestMapping(method = RequestMethod.GET)
	public void getImage(@RequestParam("profileid") Profile profile, HttpServletResponse resp) {
		byte[] data = null;
		if (profile != null) {
			if (profile.getPhoto() != null) {
				if (profile.getPhoto().getData() != null) {
					if (profile.getPhoto().getData().length != 0) {
						data = profile.getPhoto().getData();
					}
				}
			} else {
				if (profile.getLinkedInProfile() != null) {
					String linkedInPictureUrl = profile.getLinkedInProfile().getPictureUrl();
					if (linkedInPictureUrl != null && !linkedInPictureUrl.isEmpty()) {
						InputStream is = null;
						URL url;
						byte[] imageBytes;
						try {
							url = new URL(linkedInPictureUrl);
							is = url.openStream();
							imageBytes = IOUtils.toByteArray(is);
						} catch (IOException e) {
							throw new RuntimeException(msgSrc.getMessage("errorImagenLinkedin", null,null));
						} finally {
							if (is != null) {
								try {
									is.close();
								} catch (IOException e) {
									throw new RuntimeException(msgSrc.getMessage("errorImagenLinkedin", null,null));
								}
							}
						}
						try {
							resp.getOutputStream().write(imageBytes);
						} catch (IOException e) {
							throw new RuntimeException(msgSrc.getMessage("errorCargarImagen", null,null));
						}
					}
					java.io.File image = new java.io.File("src/main/resources/default_profile_image.gif");
					try {
						data = FileUtils.readFileToByteArray(image);
					} catch (IOException e) {
						throw new RuntimeException(msgSrc.getMessage("errorCargarImagenDefault", null,null));
					}
				}
			}
		}
		try {
			if (data==null){
				java.io.File image = new java.io.File("src/main/resources/default_profile_image.gif");
				data = FileUtils.readFileToByteArray(image);
			}
			resp.getOutputStream().write(data);
		} catch (IOException e) {
			throw new RuntimeException(msgSrc.getMessage("errorCargarImagen", null,null));
		}
	}

	@RequestMapping(method = RequestMethod.GET)
	protected ModelAndView ListUsers(HttpSession session, List<User> users) {
		ModelAndView mav = new ModelAndView();
		String emails = "";
		for (int i=0; i<users.size(); i++) {
			emails += users.get(i).getEmail() + (i==users.size()-1 ? "" : ",");
		}
		mav.addObject("emails", emails);
		mav.addObject("users", users);
		User userlogged = (User) session.getAttribute("user");
		mav.addObject("profiles", searchRepository.getSavedResultsByUser(userlogged));
		mav.addObject("massiveSaveForm", new MassiveSaveForm());
		mav.setViewName("user/ListUsers");
		return mav;
	}

	@RequestMapping(method = RequestMethod.GET)
	protected ModelAndView ListAdmins(HttpSession session) {
		List<User> users = null;
		ModelAndView mav = new ModelAndView();
		users = userRepository.getAdminUsers();
		if (users != null) {
			mav.addObject("users", users);
		}
		
		User userlogged = (User) session.getAttribute("user");
		mav.addObject("userlogged", userlogged);
		mav.setViewName("user/ListAdmins");
		return mav;
	}

	@RequestMapping(method = RequestMethod.GET)
	protected ModelAndView ViewPendingUserRequests() {
		List<User> pendingUsers;
		ModelAndView mav = new ModelAndView();
		pendingUsers = userRepository.getPendingUserRequests();
		if (pendingUsers != null) {
			mav.addObject("pendingUsers", pendingUsers);
			mav.addObject("massiveRequestForm", new MassiveRequestForm());
		}
		mav.setViewName("user/ViewPendingUserRequests");
		return mav;
	}

	@RequestMapping(method = RequestMethod.POST)
	protected ModelAndView AnswerPendingUsers(HttpSession sess,HttpServletRequest request, MassiveRequestForm form) {
		if (form.getUsers()!=null) {
			String[] emails = new String[form.getUsers().size()];
			int i = 0;
			if (request.getParameter("confirm") != null) {
				for (User user: form.getUsers()) {
					user.setConfirmed(true);
					emails[i++] = user.getEmail(); 
				}
				new EmailSender(emails, MailTitleBodyEnum.USER_CONFIRMATION.getTitleAndBody()).start();
			} else if (request.getParameter("deny") != null) {
				for (User user: form.getUsers()) {
					userRepository.deleteUser(user);
					emails[i++] = user.getEmail(); 
				}
				new EmailSender(emails, MailTitleBodyEnum.USER_REJECTION.getTitleAndBody()).start();
			}
		}
		sess.setAttribute("pendingRequests", userRepository.getPendingUserRequests().size());
		return ViewPendingUserRequests();		
	}
	
	@RequestMapping(method = RequestMethod.GET)
	public ModelAndView ConfirmUser(HttpSession sess, @RequestParam("userid") User user) {
		user.setConfirmed(true);
		new EmailSender(user.getEmail(), MailTitleBodyEnum.USER_CONFIRMATION.getTitleAndBody()).start();
		sess.setAttribute("pendingRequests", userRepository.getPendingUserRequests().size());
		return ViewPendingUserRequests();
	}

	@RequestMapping(method = RequestMethod.GET)
	public ModelAndView DenyUser(HttpSession sess, @RequestParam("userid") User user) {
		userRepository.deleteUser(user);
		new EmailSender(user.getEmail(), MailTitleBodyEnum.USER_REJECTION.getTitleAndBody()).start();
		sess.setAttribute("pendingRequests", userRepository.getPendingUserRequests().size());
		return ViewPendingUserRequests();
	}

	@RequestMapping(method = RequestMethod.GET)
	protected ModelAndView forgotPassword() {
		ModelAndView mav = new ModelAndView();
		mav.addObject("forgotPasswordForm", new ForgotPasswordForm());
		mav.setViewName("user/forgotPassword");
		return mav;
	}

	@RequestMapping(method = RequestMethod.POST)
	public ModelAndView forgotPassword(ForgotPasswordForm forgotPasswordForm, Errors errors) {
		forgotPasswordValidator.validate(forgotPasswordForm, errors);
		if (errors.hasErrors())
			return null;

		ModelAndView mav = new ModelAndView();
		User user = userRepository.getUserByEmail(forgotPasswordForm.getEmail());
		if (user == null) {
			mav.addObject("errorLogin", msgSrc.getMessage("emailNoEncontrado", null,null));
			mav.setViewName("user/forgotPassword");
			return mav;
		}

		MailTitleBody mtb = MailTitleBodyEnum.PASS_RETRIEVAL.getTitleAndBody();
		mtb.appendPassToBody(user.getPassword());
		new EmailSender(user.getEmail(), mtb).start();

		mav.addObject("messages", msgSrc.getMessage("passwordEnviada", null,null));
		mav.setViewName("general/index");
		return mav;
	}

	@RequestMapping(method = RequestMethod.GET)
	protected void SearchNames(HttpServletResponse response, @RequestParam("name") String name) {
		List<User> users = userRepository.searchByName(name);
		try {
			response.setContentType("text/xml");  
	        response.setHeader("Cache-Control", "no-cache");
	        String usersString = "";
	        for (User user: users) {
	        	usersString += user.getName() + " " + user.getLastName() + ",";
	        }
	        response.getWriter().write("<users>" + usersString + "</users>");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	@RequestMapping(method = RequestMethod.POST)
	protected ModelAndView SearchUser(HttpSession session, @RequestParam("name") String name) {
		List<User> users = userRepository.searchByName(name);
		User userlogged = (User)session.getAttribute("user");
		return ViewFriends(userlogged, users, msgSrc.getMessage("resultadosBusquedaTitle", null,null), msgSrc.getMessage("sinResultados", null,null));
	}
	
	@RequestMapping(method = RequestMethod.GET)
	protected ModelAndView ListFriends(HttpSession session) {
		User userlogged = (User)session.getAttribute("user");
		// Traigo el user de nuevo desde la base porque el que esta en la session no mantiene actualizado los cambios de amistades
		User userloggedrefreshed = userRepository.getUser(userlogged.getId());
		List<User> friends = userloggedrefreshed.getFriends();
		return ViewFriends(userlogged, friends, "Red Profesional", msgSrc.getMessage("sinRedProfesional", null,null));
	}
	
	private ModelAndView ViewFriends(User userlogged, List<User> users, String title, String emptyMess) {
		ModelAndView mav = new ModelAndView("user/ListFriends");
		mav.addObject("friends", users);
		mav.addObject("title", title);
		mav.addObject("emptyMess", emptyMess);
		User userloggedrefreshed = userRepository.getUser(userlogged.getId());
		mav.addObject("userlogged", userloggedrefreshed);
		return mav;
	}
	
	@RequestMapping(method = RequestMethod.GET)
	public ModelAndView AddFriend(HttpSession session, @RequestParam("user_id") User user) {
		User userlogged = (User)session.getAttribute("user");
		try {
			friendRequestRepository.newFriendRequests(new FriendRequest(userlogged, user));
		} catch (DuplicateException e) {
			ModelAndView mav = new ModelAndView("general/error");
			mav.addObject("errorTitle", "Error");
			mav.addObject("errorMsg", msgSrc.getMessage("usuarioExistenteEnRedProfesional", null,null));
			return mav;
		}
		MailTitleBody mtb = MailTitleBodyEnum.FRIEND_REQUEST.getTitleAndBody();
		mtb.appendNameToTitle(userlogged.getName() + " " + userlogged.getLastName());
		new EmailSender(user.getEmail(), mtb).start();
		return viewProfile(session, user);
	}
	
	@RequestMapping(method = RequestMethod.GET)
	protected ModelAndView FriendRequests(HttpSession session) {
		ModelAndView mav = new ModelAndView("user/ListRequests");
		User userlogged = (User)session.getAttribute("user");
		List<FriendRequest> requests = friendRequestRepository.getFriendRequestsForUser(userlogged);
		mav.addObject("requests", requests);
		return mav;
	}
	
	@RequestMapping(method = RequestMethod.GET)
	protected ModelAndView AcceptRequest(HttpSession session, @RequestParam("id") FriendRequest friendRequest) {
		friendRequest.getRequester().addFriend(friendRequest.getRequested());
		friendRequest.getRequested().addFriend(friendRequest.getRequester());
		this.friendRequestRepository.deleteFriendRequest(friendRequest);
		// Actualizo los request que hay ahora del usuario logueado
		session.setAttribute("friendRequests", friendRequestRepository.getFriendRequestsForUser((User)session.getAttribute("user")).size());
		
		return FriendRequests(session);
	}
	
	@RequestMapping(method = RequestMethod.GET)
	protected ModelAndView DenyRequest(HttpSession session, @RequestParam("id") FriendRequest friendRequest) {
		this.friendRequestRepository.deleteFriendRequest(friendRequest);
		// Actualizo los request que hay ahora del usuario logueado
		session.setAttribute("friendRequests", friendRequestRepository.getFriendRequestsForUser((User)session.getAttribute("user")).size());
		
		return FriendRequests(session);
	}
}
